package models

import (
	"context"
	"errors"
	"fmt"
	"github.com/cy77cc/hioshop/global"
	"gorm.io/gorm"
	"math/rand"
	"time"
)

type User struct {
	Model
	Nickname      string    `json:"nickname"`
	Name          string    `json:"name"`
	Username      string    `json:"username"`
	Password      string    `json:"password"`
	Gender        uint8     `json:"gender"`
	Birthday      uint      `json:"birthday"`
	RegisterTime  time.Time `json:"register_time"`
	LastLoginTime time.Time `json:"last_login_time"`
	LastLoginIp   int       `json:"last_login_ip"`
	Mobile        string    `json:"mobile"`
	RegisterIp    int       `json:"register_ip"`
	Avatar        string    `json:"avatar"`
	WeixinOpenid  string    `json:"weixin_openid"`
	NameMobile    int8      `json:"name_mobile"`
	Country       string    `json:"country"`
	Province      string    `json:"province"`
	City          string    `json:"city"`
}

func (u *User) GetUserInfoByOpenId() error {
	err := global.DB.Model(&User{}).Where("weixin_openid=?", u.WeixinOpenid).First(u).Error
	return err
}

func (u *User) UpdateUserInfo() (err error) {
	ctx := context.Background()
	get := global.REDIS.HGet(ctx, fmt.Sprintf("user:%d", u.ID), "id")
	m := make(map[string]any)
	if u.Name != "" {
		m["name"] = u.Name
	}
	if u.Mobile != "" {
		m["mobile"] = u.Mobile
	}
	if u.Avatar != "" {
		m["avatar"] = u.Avatar
	}
	if u.Nickname != "" {
		m["nickname"] = u.Nickname
	}

	// 先更新缓存，再更新数据库
	if get.Val() != "" {
		err = global.REDIS.HMSet(ctx, fmt.Sprintf("user:%d", u.ID), m).Err()
		// 命中之后加时间
		global.REDIS.Expire(ctx, fmt.Sprintf("user:%d", u.ID), time.Hour)
	}
	err = global.DB.Model(&User{}).Where(map[string]any{
		"id": u.ID,
	}).Updates(m).Error
	return err
}

func (u *User) GetUserInfoById() (err error) {
	ctx := context.Background()
	get := global.REDIS.HMGet(ctx, fmt.Sprintf("user:%d", u.ID), "id", "mobile", "name", "nickname", "avatar")
	if get.Val()[0] == nil {
		err = global.DB.Model(&User{}).Where("id=?", u.ID).
			Select("id", "mobile", "name", "nickname", "avatar").Find(u).Error
		fmt.Println()
		if err != nil || errors.Is(err, gorm.ErrRecordNotFound) {
			// 防止缓存穿透
			err = global.REDIS.HMSet(ctx, fmt.Sprintf("user:%d", u.ID), "").Err()
			return
		} else {
			err = global.REDIS.HMSet(ctx, fmt.Sprintf("user:%d", u.ID), map[string]any{
				"id":       u.ID,
				"mobile":   u.Mobile,
				"name":     u.Name,
				"nickname": u.Nickname,
				"avatar":   u.Avatar,
			}).Err()

			global.REDIS.Expire(ctx, fmt.Sprintf("user:%d", u.ID), time.Hour+time.Duration(rand.Intn(50)))
			return
		}

	}
	res, _ := get.Result()
	//fmt.Println(res)
	if res[1] != nil {
		u.Mobile = res[1].(string)
	}
	if res[2] != nil {
		u.Name = res[2].(string)
	}
	if res[3] != nil {
		u.Nickname = res[3].(string)
	}
	if res[4] != nil {
		u.Avatar = res[4].(string)
	}
	return
}

func (u *User) Create() error {
	return global.DB.Model(&User{}).Create(u).Error
}
